#include "WOB.h"
#include "MersenneTwister.h"

WOB::WOB(cl_int r1)
{
	capacitanceGPU = 0.0f;
	capacitance = 5.0f;
	countN = 10000;
	radius = r1;
	//initializeCL();
	//runCLKernels();
	//cout << "WOB: " << capacitanceGPU << endl;
}

WOB::~WOB()
{
	//cleanupCL();
}

cl_float WOB::searchCapacitanceCPU()
{
	return 5.0f;
}

// Initialize CL 
void WOB::initializeCL()
{
	cl_int status = 0;
	size_t deviceListSize;

	MyOCL::initializeCL();

	// ****************************
	// Create OpenCL memmory buffer
	// ****************************
	
	// Load CL file, build CL program object, create CL kernel object
	const char * filename  = "WOB.cl";
	string  sourceStr = convertToString(filename);
	const char * source    = sourceStr.c_str();
	size_t sourceSize[]    = { strlen(source) };

	program = clCreateProgramWithSource(
		context, 
		1, 
		&source,
		sourceSize,
		&status);
	if(status != CL_SUCCESS) 
	{ 
		printf("Error: Loading Binary into cl_program.\n");
		printError(status, "clCreateProgramWithBinary");
		return;
	}

	// create a cl program executable for all the devices specified 
	status = clBuildProgram(program, 1, devices, NULL, NULL, NULL);
	if(status != CL_SUCCESS) 
	{ 
		printf("Error: Building Program\n");
		printError(status, "clBuildProgram");
		return; 
	}

	// get a kernel object handle for a kernel with the given name 
	kernel = clCreateKernel(program, "Main", &status);
	if(status != CL_SUCCESS) 
	{  
		printf("Error: Creating Kernel from program.\n");
		printError(status, "clCreateKernel");
		return;
	}
}

void WOB::runCLKernels()
{
	cl_int   status;
	cl_event events[2];
	size_t globalThreads[1];
	size_t localThreads[1];


	globalThreads[0] = 500;
	localThreads[0] = 1;

	// === Set appropriate arguments to the kernel ===
	// number 
	status = clSetKernelArg(
		kernel, 
		0,
		sizeof(cl_uint), 
		(void *)&capacitanceGPU);
	if(status != CL_SUCCESS) 
	{ 
		printf("Error: Setting kernel argument.\n");
		printError(status, "clSetKernelArg: capacitanceGPU");
		return;
	}

	// Enqueue a kernel run call.
	status = clEnqueueNDRangeKernel(
		commandQueue,
		kernel,
		1,
		NULL,
		globalThreads,
		localThreads,
		0,
		NULL,
		&events[0]);

	if(status != CL_SUCCESS) 
	{ 
		printf("Error: Enqueueing kernel onto command queue.\n");
		printError(status, "clEnqueueNDRangeKernel");
		return;
	}

	clFinish(commandQueue);

	// wait for the kernel call to finish execution
	status = clWaitForEvents(1, &events[0]);
	if(status != CL_SUCCESS) 
	{ 
		printf(
			"Error: Waiting for kernel run to finish.\n");
		printError(status, "clWaitForEvents");
		return;
	}

	status = clReleaseEvent(events[0]);
	if(status != CL_SUCCESS)
	{
		printf("Error: clReleaseEvent.\n");
		printError(status, "events[0]");
		return;
	}
}

// Initialize Host application 
void WOB::initializeHost()
{

}
// releases OpenCL resources
void WOB::cleanupCL()
{
	MyOCL::cleanupCL();
}

// releases program's resources 
void WOB::cleanupHost()
{

}